#include <lyn_api.h>
#include <string>
#include "blockQueue.hpp"
#include "opencv2/opencv.hpp"
#include "util.hpp"
#include "videoDecoder.h"
#include "videoEncoder.h"
#include "CLI/CLI11.hpp" // 引入 CLI11 头文件

using namespace std;

int main(int argc, char *argv[])
{

  string inputFile;
  string outputFile;
  int deviceId;
  int frameCount;

  CLI::App app;
  // 添加选项
  app.add_option("-i", inputFile, "input MP4 video file path")->default_val("../data/video_decode_and_encode_sample/MOT16-09.mp4");
  app.add_option("-o", outputFile, "output H.264 video file path")->default_val("../output.h264");
  app.add_option("-d", deviceId, "lynxi device id")->default_val("0");
  app.add_option("-c", frameCount, "count of video encode frames")->default_val(500);

  CLI11_PARSE(app, argc, argv);

  // get params
  // const char *keys =
  //     "{@input_video | ../data/MOT16-09.mp4 | input MP4 video file path}"
  //     "{@output_video | ../output.h264 | output H.264 video file path}"
  //     "{@device_id | 0 | lynxi device id}"
  //     "{frame_count c | 500 | count of video encode frames}"
  //     "{help h ? |  | print help information.}";

  // cv::CommandLineParser parser(argc, argv, keys);

  // if (parser.has("help")) {
  //   parser.printMessage();
  //   return 0;
  // }

  // string inputFile = parser.get<string>(0);
  // string outputFile = parser.get<string>(1);
  // int deviceId = parser.get<int>(2);
  // int frameCount = parser.get<int>("frame_count");

  // if (!parser.check()) {
  //   parser.printErrors();
  //   return 0;
  // }

  if (!IsFileExist(inputFile))
  {
    cout << "error : input MP4 video file is not exsit." << endl;
    return 0;
  }

  if (!IsValidDevice(deviceId))
  {
    cout << "error : device id is invalid." << endl;
    return 0;
  }

  if (frameCount <= 0)
  {
    cout << "error : frame count is invalid." << endl;
    return 0;
  }

  VideoDecoder videoDec;
  VideoEncoder videoEnc;

  lynContext_t context;
  CHECK_ERR(lynCreateContext(&context, deviceId));
  CHECK_ERR(lynRegisterErrorHandler(StreamErrorHandler, nullptr));

  videoDec.Init(inputFile, File, 0, frameCount);

  lynVdecOutInfo_t outInfo;
  videoDec.GetVdecOutInfo(&outInfo);
  uint32_t nVdecOutSize = outInfo.predictBufSize;

  FramePool framePool(nVdecOutSize, 5);
  BlockQueue<lynFrame_t *> blockQueue(5);
  videoDec.Start(context, std::ref(blockQueue), std::ref(framePool));

  FramePool vencRecvFramePool(nVdecOutSize, 5);
  videoEnc.Init(outInfo, outputFile, &framePool, &vencRecvFramePool);

  bool bEos = false;
  int cnt = 0;

  while (!bEos)
  {
    lynFrame_t *pFrame;
    blockQueue.take(pFrame);
    bEos = pFrame->eos;
    videoEnc.EncodeImage(pFrame);
    if (!bEos)
    {
      std::cout << "frame num : " << ++cnt << std::endl;
    }
  }

  videoDec.Stop();
  videoDec.UnInit();
  videoEnc.UnInit();

  return 0;
}
